#include "mobilestoragelistview.h"

#include <QDebug>
#include <QFileInfo>
#include <QApplication>

const int TAG_INFO = 100;
const int ICON_MODE_ICON_WIDTH = 64;
const int ICON_MODE_ICON_HEIGHT = 64;
const int LIST_MODE_ICON_WIDTH = 32;
const int LIST_MODE_ICON_HEIGHT = 32;
const int ICON_MODE_GRID_WIDTH = 125;
const int ICON_MODE_GRID_HEIGHT = 132;
const int ICON_MODE_ITEM_HEIGHT = 114;
const int ICON_MODE_TOP_MARGIN = 18;
const int ICON_MODE_BOTTOM_MARGIN = 23;
const int ICON_MODE_SPACING = 18;
const int LIST_MODE_ITEM_HEIGHT = 52;
const int LIST_MODE_TOP_MARGIN = 7;
const int LIST_MODE_BOTTOM_MARGIN = 7;

MobileStorageListView::MobileStorageListView(QWidget *parent) : QListView(parent)
{
    m_listModel = new QStandardItemModel(this);
    setModel(m_listModel);
    m_listDelefate = new MobileStorageListDelegate(this);
    setItemDelegate(m_listDelefate);

    //自适应布局
    this->setResizeMode(QListView::Adjust);
    //列表中的图标不可拖动
    this->setMovement(QListView::Static);
    //去边框
    this->setFrameShape(QListView::NoFrame);
    //不可编辑
    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    //设置选中模式为选中行
    this->setSelectionBehavior(QAbstractItemView::SelectRows);
    //设置按ctrl键选中多个
    this->setSelectionMode(QAbstractItemView::ExtendedSelection);
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    this->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
    //    this->verticalScrollBar()(20);
    //设置项大小相同
    this->setUniformItemSizes(true);
    this->setContextMenuPolicy(Qt::CustomContextMenu);

    m_menu = new QMenu();
    initMenuAction();

    connect(this, &MobileStorageListView::doubleClicked, this, &MobileStorageListView::slotDoubleClicked);
    connect(this, &MobileStorageListView::clicked, this, &MobileStorageListView::slotClicked);
    connect(this, &MobileStorageListView::customContextMenuRequested, this, &MobileStorageListView::slotContextMenu);
}

MobileStorageListView::~MobileStorageListView()
{
    if (m_menu != nullptr) {
        delete m_menu;
        m_menu = nullptr;
    }

    if (m_openAction != nullptr) {
        delete m_openAction;
        m_openAction = nullptr;
    }
}

void MobileStorageListView::initMenuAction()
{
    m_menu->clear();
    m_openAction = new QAction(tr("Open")); // Open打开
    connect(m_openAction, &QAction::triggered, this, &MobileStorageListView::slotOpenTriggered);
}

void MobileStorageListView::slotContextMenu(const QPoint &pos)
{
    if (!this->indexAt(pos).isValid()) {
        return;
    }

    QModelIndex index = this->indexAt(pos);
    FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
    QString name = fileInfo.name();

    Q_EMIT sigMouseRelease();

    m_menu->addAction(m_openAction);
    m_menu->popup(QCursor::pos());
}

void MobileStorageListView::setViewModeFlag(QListView::ViewMode mode)
{
    if (mode == QListView::IconMode) {
        this->setIconSize(QSize(ICON_MODE_ICON_WIDTH, ICON_MODE_ICON_HEIGHT));
        this->setSpacing(0);
        this->setGridSize(QSize(ICON_MODE_GRID_WIDTH, ICON_MODE_GRID_HEIGHT));
    } else if (mode == QListView::ListMode) {
        this->setIconSize(QSize(LIST_MODE_ICON_WIDTH, LIST_MODE_ICON_HEIGHT));
        this->setSpacing(4);
        this->setGridSize(QSize(-1, -1));
    }

    setViewMode(mode);

    if (this->viewMode() == QListView::IconMode) {
        for (int i = 0; i < m_fileInfo.size(); i++) {
            QModelIndex index = this->model()->index(i, 0, QModelIndex());
            FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
            QString listName = fileInfo.name();
            QVariant metaName;
            metaName.setValue(listName);
            this->model()->setData(index, metaName, Qt::DisplayRole);
        }
    } else {
        for (int i = 0; i < m_fileInfo.size(); i++) {
            QModelIndex index = this->model()->index(i, 0, QModelIndex());
            FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
            QString listName = fileInfo.name();
            qint64 size = fileInfo.size();

            QVariant metaName;
            metaName.setValue(listName);
            QString sizeStr = getSize(size);
            QVariant metaSize;
            metaSize.setValue(sizeStr);
            if (fileInfo.type() == FileInfo::FILE_TYPE::TYPE_DIR) {
                this->model()->setData(index, metaName, Qt::DisplayRole);
            } else {
                this->model()->setData(index, metaName, Qt::DisplayRole);
                this->model()->setData(index, metaSize, Qt::UserRole);
            }
        }
    }

    if (this->viewMode() == QListView::IconMode) {
        setWidgetIconItemHeight();
    } else {
        setWidgetListItemHeight();
    }
}

QString MobileStorageListView::getSize(qint64 sizeByte)
{
    QString text;
    if (sizeByte < 1024) {
        text = QString("%1B").arg(QString::number(sizeByte / 1.0, 'f', 1));
        return text;
    } else if (sizeByte < 1024 * 1024) {
        text = QString("%1KB").arg(QString::number(sizeByte / 1024.0, 'f', 1));
        return text;
    } else if (sizeByte < 1024 * 1024 * 1024) {
        text = QString("%1MB").arg(QString::number(sizeByte / 1024.0 / 1024.0, 'f', 1));
        return text;
    }
    text = QString("%1GB").arg(QString::number(sizeByte / 1024.0 / 1024.0 / 1024.0, 'f', 1));
    return text;
}

void MobileStorageListView::setWidgetIconItemHeight()
{
    int itemCount;
    int count = this->width() / ICON_MODE_GRID_WIDTH;
    if (m_listModel->rowCount() > 0) {
        if (m_listModel->rowCount() % count == 0) {
            itemCount = m_listModel->rowCount() / count;
        } else {
            itemCount = m_listModel->rowCount() / count + 1;
        }
    }
    if (m_listModel->rowCount() > 0) {
        if (itemCount == 1) {
            m_height = itemCount * ICON_MODE_ITEM_HEIGHT + ICON_MODE_TOP_MARGIN + ICON_MODE_BOTTOM_MARGIN;
        } else {
            m_height = (itemCount - 1) * (ICON_MODE_ITEM_HEIGHT + ICON_MODE_SPACING) + ICON_MODE_ITEM_HEIGHT;
        }
    }
}

void MobileStorageListView::setWidgetListItemHeight()
{
    int itemCount = m_listModel->rowCount();
    if (itemCount > 0) {
        if (itemCount == 1) {
            m_height = itemCount * LIST_MODE_ITEM_HEIGHT + LIST_MODE_TOP_MARGIN + LIST_MODE_BOTTOM_MARGIN;
        } else {
            m_height = (itemCount - 1) * (LIST_MODE_ITEM_HEIGHT + 4) + LIST_MODE_ITEM_HEIGHT + LIST_MODE_TOP_MARGIN
                       + LIST_MODE_BOTTOM_MARGIN;
        }
    }
}

void MobileStorageListView::setResize()
{
    Q_EMIT signalSetResize(m_height);
}

void MobileStorageListView::setFileList(const QMap<QString, FileInfo> &listStruct)
{
    m_listModel->clear();

    QMap<QString, FileInfo>::const_iterator it = listStruct.begin();
    QMap<QString, FileInfo> nonFolderList; // 临时存储非目录项
    while (it != listStruct.end()) {
        QStandardItem *item = new QStandardItem;

        if (it.value().type() == FileInfo::FILE_TYPE::TYPE_DIR) {
            item->setIcon(QIcon::fromTheme("folder"));
            //设置文件名
            item->setData(it.value().name(), Qt::DisplayRole);
            //标记文件名
            item->setData(it.value(), Qt::DisplayRole + TAG_INFO);
            item->setToolTip(it.value().name());
            m_listModel->appendRow(item);
            m_fileInfo.append(it.value());
        } else {
            // 不是文件夹，暂时存储，等待文件夹插入完毕再插入
            nonFolderList.insert(it.key(), it.value());
            m_fileInfo.append(it.value());
        }
        it++;
    }
    it = nonFolderList.begin();
    while (it != nonFolderList.end()) {
        QStandardItem *item = new QStandardItem;
        if (it.value().type() == FileInfo::FILE_TYPE::TYPE_TXT) {
            item->setIcon(QIcon::fromTheme("text"));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_VIDEO) {
            item->setIcon(QIcon::fromTheme("video"));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_IMAGE) {
            item->setIcon(QIcon::fromTheme("image-x-generic"));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_AUDIO) {
            item->setIcon(QIcon::fromTheme("audio-x-generic"));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_DOC) { // word
            item->setIcon(QIcon(QIcon::fromTheme("application-msword")));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_EXCEL) { // excel
            item->setIcon(QIcon(QIcon::fromTheme("application-msexcel")));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_PDF) { // pdf
            item->setIcon(QIcon(QIcon::fromTheme("application-pdf")));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_PPTX) { // ppt
            item->setIcon(QIcon(QIcon::fromTheme("application-mspowerpoint")));
        } else if (it.value().type() == FileInfo::FILE_TYPE::TYPE_ZIP) { // zip
            item->setIcon(QIcon(QIcon::fromTheme("application-archive-zip")));
        } else {
            item->setIcon(QIcon::fromTheme("unknown"));
        }
        //设置文件名
        item->setData(it.value().name(), Qt::DisplayRole);
        //标记文件名
        item->setData(it.value(), Qt::DisplayRole + TAG_INFO);
        item->setToolTip(it.value().name());
        m_listModel->appendRow(item);
        it++;
    }

    if (this->viewMode() == QListView::IconMode) {
        setWidgetIconItemHeight();
    } else {
        setWidgetListItemHeight();
    }
}

void MobileStorageListView::slotDoubleClicked(const QModelIndex &index)
{
    if (index.isValid()) {
        Q_EMIT sigHideCopyToComputerWidget();
        qDebug() << "MobileStorageListView slotDoubleClicked file";
        FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
        QString listName = fileInfo.name();
        QString filePath = fileInfo.getPath();
        int listType = fileInfo.type();

        if (listType == FileInfo::FILE_TYPE::TYPE_DIR) {
            qInfo() << "dir double clicked" << listName;
            m_listModel->clear();
            //面包屑路径
            Q_EMIT sigFileName(listName);
            Q_EMIT sigHideCopyToComputerWidget();
            qDebug() << "MobileStorageListView slotDoubleClicked dir";
        } else {
            qInfo() << "file double clicked" << filePath;
            Q_EMIT sigMenuFileName(filePath);
        }
    }
}

void MobileStorageListView::slotClicked(const QModelIndex &index)
{
    if (index.isValid()) {
        QList<FileInfo> nameList;
        this->selectAllNames(nameList);
        Q_EMIT sigSelectDataList(nameList);
    }
}

void MobileStorageListView::slotOpenTriggered()
{
    int row = this->currentIndex().row();
    QModelIndex index = this->model()->index(row, 0, QModelIndex());
    FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();

    QString fileName = fileInfo.name();
    QString filePath = fileInfo.getPath();
    int listType = fileInfo.type();

    if (listType == FileInfo::FILE_TYPE::TYPE_DIR) {
        qInfo() << "dir menu open" << fileName;
        //面包屑路径
        Q_EMIT sigFileName(fileName);
        Q_EMIT sigHideCopyToComputerWidget();
    } else {
        qInfo() << "file menu open" << filePath;
        Q_EMIT sigMenuFileName(filePath);
    }
}

void MobileStorageListView::mousePressEvent(QMouseEvent *event)
{
    bool isListArea = this->indexAt(event->pos()).isValid();
    if (!isListArea) {
        if (QApplication::keyboardModifiers() != Qt::ControlModifier) {
            clearSelection();
            update();
        }
        if (event->source() != Qt::MouseEventSynthesizedByQt) {
            clearSelection();
            update();
        }
    }

    if (QApplication::keyboardModifiers() == Qt::NoModifier) {
        Q_EMIT sigMousePress(event);
    }
    QListView::mousePressEvent(event);
}

void MobileStorageListView::mouseReleaseEvent(QMouseEvent *event)
{
    QListView::mouseReleaseEvent(event);
    Q_EMIT sigMouseRelease();
}

void MobileStorageListView::keyPressEvent(QKeyEvent *event)
{
    QListView::keyPressEvent(event);
    if ((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_A)) {
        QList<FileInfo> nameList;
        this->selectAllNames(nameList);
        Q_EMIT sigSelectDataList(nameList);
        Q_EMIT sigSelectAll();
    }
}

void MobileStorageListView::selectAllNames(QList<FileInfo> &fileList)
{
    fileList.clear();
    for (QModelIndex index : selectionModel()->selectedIndexes()) {
        FileInfo fileInfo = index.data(Qt::DisplayRole + TAG_INFO).value<FileInfo>();
        fileList.append(fileInfo);
    }
    return;
}

void MobileStorageListView::setViewHeight()
{
    if (this->viewMode() == QListView::IconMode) {
        setWidgetIconItemHeight();
    } else {
        setWidgetListItemHeight();
    }

    Q_EMIT signalSetResize(m_height);
}
